﻿using Abp.Application.Features;
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.Extensions;
using Abp.Linq.Extensions;
using Abp.Runtime.Session;
using Abp.UI;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Mt.Site.Application.ContentManagement.Dto;
using Mt.Site.Application.Dto.ManualSynchorize;
using Mt.Site.Core.ContentManagement;
using Mt.Site.Core.ContentManagement.Entities;
using Mt.Site.Core.ContentManagement.Features;
using Mt.Site.Core.ContentManagement.Permissions;
using Mt.Site.Core.Navigations.Entities;
using Mt.Site.Core.Synchronization;
using Mt.Site.Core.Synchronization.ContentManagement;
using Mt.Site.Core.Synchronization.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;

namespace Mt.Site.Application.ContentManagement.Synchronization
{
    [RequiresFeature(ContentFeatures.ContentFeature)]
    public class ContentSyncAppService : MtSiteAppServiceBase, IContentSyncAppService
    {
        private readonly IContentManualSyncManager _contentManualSyncManager;

        private readonly IRepository<Content, Guid> _contentRepository;

        private readonly ISynchronizationHelper _synchronizationHelper;

        private readonly IRepository<RouteSetting, Guid> _routeSettingRepository;

        private readonly IContentManager _contentManager;

        public ContentSyncAppService(
            IContentManualSyncManager contentManualSyncManager,
            IRepository<Content, Guid> contentRepository,
            ISynchronizationHelper synchronizationHelper,
            IRepository<RouteSetting, Guid> routeSettingRepository,
            IContentManager contentManager)
        {
            _contentManualSyncManager = contentManualSyncManager;
            _contentRepository = contentRepository;
            _synchronizationHelper = synchronizationHelper;
            _routeSettingRepository = routeSettingRepository;
            _contentManager = contentManager;
        }


        [HttpPost]
        [AbpAuthorize(ContentPermissions.Pages_Manage_Content_Synchorization)]
        public async Task<PagedResultDto<MotherSiteDataOut>> GetContentMotherInfoAsync(PagedMotherSiteContentInput input)
        {
            using (CurrentUnitOfWork.DisableFilter(
                AbpDataFilters.MayHaveTenant,
                AbpDataFilters.MustHaveTenant,
                MtSiteConsts.AbpDataFilters.MustHaveLanguage))
            {
                var motherSiteInfo = _synchronizationHelper.GetMotherSiteInfo(
                    AbpSession.GetTenantId(), AbpSession.CultureName());

                if (motherSiteInfo == null)
                {
                    return null;
                }

                //同步的前提是双方有一样的配置
                input.CustomKey = await _contentManager.GetCustomKey(input.CustomKey, input.MenuId);
                //更换为源数据的RelateId
                input.RelateId = await GetSourceRelateId(input.RelateId, motherSiteInfo.MotherTenantId, motherSiteInfo.MotherLanguage);

                var masterDatas = new List<MotherSiteDataOut>();
                int count = 0;
                if (input.RelateId != Guid.Empty)
                {
                    var q = _contentRepository.GetAll()
                                 .Where(item => item.TenantId == motherSiteInfo.MotherTenantId && item.Language == motherSiteInfo.MotherLanguage && item.MenuId == input.MenuId && item.Key == input.CustomKey && item.RelateId == input.RelateId)
                                 .WhereIf(!input.Filter.IsNullOrWhiteSpace(), item => item.Title.Contains(input.Filter));

                    q = !input.Sorting.IsNullOrWhiteSpace()
                            ? q.OrderBy(input.Sorting)
                            : q.OrderByDescending(t => t.Order).ThenByDescending(t => t.PublishTime).ThenByDescending(t => t.CreationTime);
                    count = q.Count();
                    var list = await q.PageBy(input).ToListAsync();

                    foreach (var item in list)
                    {
                        masterDatas.Add(new MotherSiteDataOut
                        {
                            Id = item.Id,
                            Title = item.Title,
                            CreationTime = item.CreationTime,
                            LastModificationTime = item.LastModificationTime
                        });
                    }
                }
                return new PagedResultDto<MotherSiteDataOut>(count, masterDatas);
            }
        }

        private async Task<Guid?> GetSourceRelateId(Guid? relateId, int motherTenantId, string motherLanguage)
        {
            if (relateId != null)
            {
                var Entity_Son = await _contentRepository.FirstOrDefaultAsync(relateId.Value);
                if (Entity_Son != null)
                {
                    var Entity_Mother = await _contentRepository.FirstOrDefaultAsync(
                            item => item.AuxiliaryId == Entity_Son.AuxiliaryId && item.TenantId == motherTenantId && item.Language == motherLanguage);

                    if (Entity_Mother != null)
                    {
                        return Entity_Mother.Id;
                    }
                    else
                    {
                        //母站中没有对应的关联数据
                        return Guid.Empty;
                    }
                }
                else
                {
                    //relateId无效，导致复制中断。
                    return Guid.Empty;
                }
            }

            return null;
        }
        [AbpAuthorize(ContentPermissions.Pages_Manage_Content_Synchorization)]
        public ManualSyncOut ManualContentSynchorize(ManualSyncInput input)
        {
            var toId = _contentManualSyncManager.CreateOrUpdateContentManualSync(
                    new CreateOrUpdateSynchorizeStore
                    {
                        Id = input.Id,
                        ToTenantId = AbpSession.GetTenantId(),
                        TargetLanguage = AbpSession.CultureName()
                    });

            if (toId != Guid.Empty)
            {
                return new ManualSyncOut
                {
                    SyncResult = true
                };
            }

            return new ManualSyncOut
            {
                SyncResult = false
            };
        }

        [AbpAuthorize(ContentPermissions.Pages_Manage_Content_Synchorization)]
        public ManualSyncOut ManualContentSynchorizeById(ManualSyncTwoInput input)
        {
            using (CurrentUnitOfWork.DisableFilter(
                AbpDataFilters.MayHaveTenant,
                AbpDataFilters.MustHaveTenant,
                MtSiteConsts.AbpDataFilters.MustHaveLanguage))
            {
                var motherSiteInfo = _synchronizationHelper
                    .GetMotherSiteInfo(AbpSession.GetTenantId(), AbpSession.CultureName());

                if (motherSiteInfo == null)
                {
                    throw new UserFriendlyException(L("NoMotherSite"));
                }

                var currentEntity = _contentRepository.FirstOrDefault(input.Id);

                if (currentEntity.SourceID == null || currentEntity.SourceID == Guid.Empty)
                {
                    throw new UserFriendlyException(L("NoSourceDataInMotherSite"));
                }

                var motherEntity = _contentRepository.FirstOrDefault(
                    item => item.Id == currentEntity.SourceID.Value && item.Language == motherSiteInfo.MotherLanguage && item.TenantId == motherSiteInfo.MotherTenantId);

                //母站与子站的数据间需要有相同的内容配置（类型），才能进行同步
                if (motherEntity != null && motherEntity.Key == currentEntity.Key)
                {
                    var toId = _contentManualSyncManager.CreateOrUpdateContentManualSync(
                            new CreateOrUpdateSynchorizeStore
                            {
                                ToTenantId = AbpSession.GetTenantId(),
                                Id = motherEntity.Id,
                                TargetLanguage = AbpSession.CultureName()
                            });

                    if (toId != Guid.Empty)
                    {
                        return new ManualSyncOut
                        {
                            SyncResult = true
                        };
                    }
                }
            }
            return new ManualSyncOut
            {
                SyncResult = false
            };
        }
    }
}
